package main

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/chromedp/cdproto/network"
	"github.com/chromedp/chromedp"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"runtime"
	"strings"
	"sync"
	"time"
	"wxReadShare/logger"
	"wxReadShare/pie"
)

// 获取Chromium路径 (Linux系统)
func getChromiumPath() string {
	// 尝试多个可能路径
	paths := []string{
		"/usr/bin/chromium-browser",
		"/usr/bin/chromium",
		"/usr/bin/chrome",
		"/usr/bin/google-chrome",
		"/usr/bin/google-chrome-stable",
	}

	for _, path := range paths {
		if _, err := os.Stat(path); err == nil {
			return path
		}
	}

	// 通过系统路径查找
	if path, err := exec.LookPath("chromium-browser"); err == nil {
		return path
	}

	return "" // 如果都找不到，让chromedp使用默认值
}

// 优化启动参数
func getOptimizedOptions(logg logger.Logger) []chromedp.ExecAllocatorOption {
	// 基础选项
	opts := []chromedp.ExecAllocatorOption{
		chromedp.UserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"),
		chromedp.WindowSize(1920, 1080),
		chromedp.Flag("headless", true),
		chromedp.Flag("disable-gpu", true),
		chromedp.Flag("no-sandbox", true),
		chromedp.Flag("disable-dev-shm-usage", true),
		chromedp.Flag("ignore-certificate-errors", true),
	}

	// 添加平台特定优化
	if runtime.GOOS == "linux" {
		// Linux系统优化参数
		opts = append(opts,
			chromedp.Flag("disable-background-timer-throttling", true),
			chromedp.Flag("disable-renderer-backgrounding", true),
			chromedp.Flag("disable-ipc-flooding-protection", true),
			chromedp.Flag("enable-features", "NetworkService,NetworkServiceInProcess"),
		)

		// 设置Chromium路径
		if chromiumPath := getChromiumPath(); chromiumPath != "" {
			opts = append(opts, chromedp.ExecPath(chromiumPath))
			logg.Infof("使用Chromium路径: %s", chromiumPath)
		} else {
			logg.Info("未找到Chromium，使用默认浏览器")
		}
	} else {
		// Windows系统优化参数
		opts = append(opts,
			chromedp.Flag("disable-blink-features", "AutomationControlled"),
			chromedp.Flag("disable-features", "CalculateNativeWinOcclusion"),
		)
	}

	// 添加通用优化参数
	opts = append(opts,
		chromedp.Flag("blink-settings", "imagesEnabled=false"),
		chromedp.Flag("disable-javascript", false), // 微信读书需要JS
	)

	return opts
}

func GetBookInfo(logg logger.Logger, cache *pie.FileCache, bookId string) error {
	// 目标页面URL
	url := fmt.Sprintf("https://weread.qq.com/book-detail?type=1&v=%s", bookId)

	// 1. 创建浏览器配置选项 (根据系统优化)
	opts := getOptimizedOptions(logg)

	// 2. 创建浏览器上下文
	allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
	defer cancel()

	ctx, cancel := chromedp.NewContext(
		allocCtx,
		chromedp.WithLogf(logg.Infof),
		chromedp.WithDebugf(logg.Infof),
	)
	defer cancel()

	// 设置超时时间
	ctx, cancel = context.WithTimeout(ctx, 23*time.Second)
	defer cancel()

	// 3. 存储结果的变量
	var bookInfo string
	var statusCode int = -1
	var statusCodeMutex sync.Mutex
	var wg sync.WaitGroup

	// 4. 设置网络监听器
	wg.Add(1)
	chromedp.ListenTarget(ctx, func(ev interface{}) {
		switch ev := ev.(type) {
		case *network.EventResponseReceived:
			resp := ev.Response
			// 检查是否是主文档响应
			if ev.Type == network.ResourceTypeDocument && resp.URL == url {
				statusCodeMutex.Lock()
				statusCode = int(resp.Status)
				statusCodeMutex.Unlock()
				wg.Done() // 主文档响应到达
			}
		}
	})

	// 5. 执行任务链
	startTime := time.Now()
	logg.Info("开始获取书籍信息...")

	err := chromedp.Run(ctx,
		// 启用网络域
		network.Enable(),
		// 屏蔽不必要资源
		chromedp.ActionFunc(func(ctx context.Context) error {
			return network.SetBlockedURLs([]string{
				"*.jpg", "*.jpeg", "*.png", "*.gif", "*.webp",
				"*.woff", "*.woff2", "*.ttf", "*.svg",
				"*.css",
				"*.mp4", "*.mpeg", "*.avi", "*.mov",
			}).Do(ctx)
		}),

		// 导航到目标页面
		chromedp.Navigate(url),

		// 等待主文档响应
		chromedp.ActionFunc(func(ctx context.Context) error {
			wg.Wait() // 等待主文档响应到达
			statusCodeMutex.Lock()
			defer statusCodeMutex.Unlock()

			if statusCode != 200 {
				return fmt.Errorf("HTTP状态码非200: %d", statusCode)
			}
			return nil
		}),

		// 等待数据可用
		chromedp.Poll(`() => {
			try {
				if (window.__NUXT__ && 
					window.__NUXT__.data && 
					window.__NUXT__.data[0] && 
					window.__NUXT__.data[0].bookInfo) {
					return true;
				}
				return false;
			} catch (e) {
				console.error('轮询错误:', e);
				return false;
			}
		}`, nil,
			chromedp.WithPollingInterval(1*time.Second),
			chromedp.WithPollingTimeout(20*time.Second),
		),

		// 获取数据
		chromedp.Evaluate(`JSON.stringify(window.__NUXT__.data[0].bookInfo)`, &bookInfo),
	)

	duration := time.Since(startTime)
	if err != nil {
		logg.Infof("运行失败 (耗时: %v): %v", duration.Round(time.Millisecond), err)
		return err
	}

	if bookInfo == "" {
		err := fmt.Errorf("解析书籍失败")
		logg.Info(err)
		return err
	}

	logg.Infof("成功获取书籍信息 (耗时: %v)", duration.Round(time.Millisecond))
	var wxReadObj WxReadBook
	if err := json.Unmarshal([]byte(bookInfo), &wxReadObj); err != nil {
		logg.Info("解析错误:", err)
		return err
	}

	// 替换封面图
	wxReadObj.Cover = strings.ReplaceAll(wxReadObj.Cover, "/t6_", "/t9_")
	wxReadObj.OrgId = bookId

	// 提取日期
	re := regexp.MustCompile(`^(\d{4}-\d{2}-\d{2})`)
	match := re.FindStringSubmatch(wxReadObj.PublishDate)
	if len(match) > 1 {
		wxReadObj.PublishDate = match[1]
	}

	jsonPretty, err := json.MarshalIndent(wxReadObj, "", "  ")
	if err != nil {
		logg.Info("编码错误:", err)
		return err
	}

	if wxReadObj.BookID == "" {
		err := fmt.Errorf("获取失败 %s", bookId)
		logg.Info(err)
		return err
	}

	// 保存结果
	saveToFile(logg, cache, string(jsonPretty), bookId+"_info.json")

	logg.Infof("%s\n", time.Now())

	// 清理浏览器缓存
	cleanBrowserCache(logg)

	return nil
}

// 清理浏览器缓存 (减少内存占用)
func cleanBrowserCache(logg logger.Logger) {
	if runtime.GOOS == "linux" {
		// 清理Chromium缓存
		cacheDirs := []string{
			filepath.Join(os.Getenv("HOME"), ".cache", "chromium"),
			filepath.Join(os.Getenv("HOME"), ".config", "chromium"),
			"/tmp/.com.google.Chrome*",
		}

		for _, dir := range cacheDirs {
			if _, err := os.Stat(dir); err == nil {
				exec.Command("rm", "-rf", dir).Run()
				logg.Infof("已清理缓存目录: %s", dir)
			}
		}
	} else {
		// Windows清理命令
		exec.Command("cmd", "/c", "del /q /s %TEMP%\\*").Run()
	}
}

// 保存数据到文件
func saveToFile(logg logger.Logger, cache *pie.FileCache, data, filename string) {
	// 尝试解析JSON
	var jsonData interface{}
	if err := json.Unmarshal([]byte(data), &jsonData); err != nil {
		logg.Infof("JSON解析失败: %v", err)
	} else {
		// 格式化JSON
		prettyJSON, err := json.MarshalIndent(jsonData, "", "  ")
		if err != nil {
			logg.Infof("JSON格式化失败: %v", err)
			prettyJSON = []byte(data) // 使用原始数据
		}

		if err := cache.Set(filename, prettyJSON); err != nil {
			logg.Infof("Failed to set cache: %v\n", err)
		}
	}
}
